﻿package com.smart.events.touch {
	
	import flash.display.InteractiveObject;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.utils.Timer; 
	
	// manages assets over, out, press, release states 

	public class TouchEventHandler  {
		       
		// the object we are listening to 		
		private var _target:InteractiveObject;
		
		// our touch points 
		private var _stageX:int;
		private var _stageY:int;
		
		private var _localX:int; 
		private var _localY:int; 
		
		private var _dispatchedPress:Boolean = false; 
		private var _pressPoint:Point; 	

		// debug mode 		
		private var _debugMode : Boolean = false; 
					
		public function TouchEventHandler() {

			debug("TouchEventHandler: init");
		}

		// call this to start interaction 		
		public function register ( _tar:InteractiveObject ) : void {
			init(_tar); 
		}
		
		// removes all interaction 
		public function unregister () : void {
			dispose(); 		
		}

		// listen to events we care about
		private function init ( _tar:InteractiveObject ):void {				
			_target = _tar; 			
			_target.addEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler);
			_target.addEventListener(MouseEvent.MOUSE_OVER,mouseOverHandler); 
		}
		
		// removes all events 
		private function dispose() : void {
			_target.removeEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler);
			_target.removeEventListener(MouseEvent.MOUSE_OVER,mouseOverHandler); 
			_target.stage.removeEventListener(MouseEvent.MOUSE_UP,mouseUpHandler); 
			_target.removeEventListener(MouseEvent.MOUSE_OUT,mouseOutHandler); 			
		}
	
		// listen to mouse down 
		private function mouseDownHandler(event:MouseEvent):void {

			debug("TouchEventHanlder: DOWN handler called"); 

			// new events to listen to 
			_target.stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);			
			
			// events to remove 
			_target.removeEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler); 

			// starting events 
			start_press(event); 
		}
		
		// only used on mouse down 
		private function start_press (event:MouseEvent) : void {

			dispatch(TouchEvent.TOUCH_PRESS);
									
			// where we pressed  
			_pressPoint = new Point(event.stageX,event.stageY); 	
			_dispatchedPress = false; 
	
			// update where touch occured  
			_stageX = event.stageX;
			_stageY = event.stageY;			

			// from local
			_localX = event.localX; 
			_localY = event.localY; 

		}
		
		private function mouseUpHandler(event:MouseEvent):void {
						
			debug("TouchEventManager: MOUSE UP " + event.target ); 

			// listen to down again 
			_target.addEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler); 
		
			// no longer interested in mouse up 
			_target.stage.removeEventListener(MouseEvent.MOUSE_UP,mouseUpHandler); 			

			// release should only occur if we actually released on top of the object 
			if ( _target.hitTestPoint(event.stageX,event.stageY) )  {						
					
				dispatch(TouchEvent.TOUCH_RELEASE);

				// update where touch occured 
				_stageX = event.stageX;
				_stageY = event.stageY;	
				
				_localX = event.localX; 
				_localY = event.localY; 
						
			}
	
			// get ready for next interaction 			
			reset_for_next(); 
		}
		
		
		// reset whatever you need for the next mouse down event 
		private function reset_for_next () : void {			
			_dispatchedPress = false; 			
		}
		
		// since this is a touch event, mouse over really just means you dragged your finger
		// over an item 
		private function mouseOverHandler ( e:MouseEvent ) : void {
			
			debug("TouchEventHanlder: OVER called"); 

			// remove 
			_target.removeEventListener(MouseEvent.MOUSE_OVER,mouseOverHandler); 		

			// add
			_target.addEventListener(MouseEvent.MOUSE_OUT,mouseOutHandler); 		
			
			// dispatch event 
			dispatch(TouchEvent.TOUCH_OVER); 
		
		}
		
		private function mouseOutHandler ( e:MouseEvent ) : void {

			debug("TouchEventHanlder: OUT called " + e.target ); 
			
			// ignore if out is not this object 
			if ( e.target != _target ) {
				debug("TouchEventHandler: not same target ignore ");
				return; 	
			}			
		
			// remove and add 
			_target.removeEventListener(MouseEvent.MOUSE_OUT,mouseOutHandler); 

			// just need to remove over 
			_target.addEventListener(MouseEvent.MOUSE_OVER,mouseOverHandler); 		
					
			// dispatch our event 
			dispatch(TouchEvent.TOUCH_OUT); 
			
		}
					
		// how to dispatch the event 
		private function dispatch(type:String):void {
			debug("TouchEventHandler: dispatch " + type);
			_target.dispatchEvent(new TouchEvent(type,this));
		}
		
		// accessor methods /////////////////
		
		public function get stageX():int {
			return _stageX;
		}
		
		public function get stageY():int {
			return _stageY;
		}
		
		public function get localX () : int {	
			return _localX; 
		}
		
		public function get localY () : int {
			return _localY; 
		}
		
		// for debugging ///// 
		private function debug ( str:String ) : void {			
			if ( _debugMode ) trace(str); 
		}
	}
}